package com.ruoyi.network.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.net.NetUtil;
import com.alibaba.excel.EasyExcelFactory;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.network.domain.entity.IpAddress;
import com.ruoyi.network.domain.entity.IpRange;
import com.ruoyi.network.enums.UasgeStatusEnum;
import com.ruoyi.network.mapper.IpAddressMapper;
import com.ruoyi.network.model.vo.*;
import com.ruoyi.network.service.IIpAddressService;
import com.ruoyi.network.service.IIpRangeService;
import com.ruoyi.network.service.listener.IpRangeListener;
import com.ruoyi.network.utils.IpAddressUtil;
import com.ruoyi.network.utils.IpRangeUtil;
import com.ruoyi.system.service.ISysUserService;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.ruoyi.network.utils.IpRangeUtil.rangeListToMap;

/**
 * IP地址维护结构Service业务层处理
 *
 * @author lyp
 * @date 2024-12-13
 */
@Service
public class IpAddressServiceImpl extends ServiceImpl<IpAddressMapper, IpAddress> implements IIpAddressService {
    @Resource
    private IpAddressMapper ipAddressMapper;
    @Resource
    private IIpRangeService rangeService;
    @Resource
    private ISysUserService sysUserService;

    /**
     * 查询IP地址维护结构
     *
     * @param id IP地址维护结构主键
     * @return IP地址维护结构
     */
    @Override
    public IpAddress selectIpAddressById(Long id) {
        return getBaseMapper().selectById(id);
    }

    /**
     * 查询IP地址维护结构列表
     *
     * @param vo 分页参数
     * @return IP地址维护结构
     */
    @Override
    public TableDataInfo selectIpAddressList(IpAddressPageVO vo) {
        Page<IpAddress> page = new Page<>(vo.getPage(), vo.getSize());

        Page<IpAddress> ipAddressPage = getBaseMapper().selectPage(page, Wrappers.<IpAddress>lambdaQuery()
                .eq(Objects.nonNull(vo.getRangeId()), IpAddress::getRangeId, vo.getRangeId())
                .eq(Objects.nonNull(vo.getUsageBizId()), IpAddress::getUsageBizId, vo.getUsageBizId())
        );

        if (ipAddressPage.getTotal() == 0) {
            return new TableDataInfo(Collections.emptyList(), 0);
        }
        return new TableDataInfo(dataPostProcess(ipAddressPage.getRecords()), Integer.parseInt(String.valueOf(ipAddressPage.getTotal())));
    }

    /**
     * 数据后置处理
     *
     * @param records 查询结果
     * @return List<IpAddressResponseVO> 处理后数据
     */
    private List<IpAddressResponseVO> dataPostProcess(List<IpAddress> records) {
        if (CollUtil.isEmpty(records)) {
            return Collections.emptyList();
        }
        List<Long> userIds = records.stream().map(IpAddress::getUsageUserId).collect(Collectors.toList());
        List<Long> rangeIds = records.stream().map(IpAddress::getRangeId).collect(Collectors.toList());

        Map<Long, SysUser> userMap = sysUserService.findByIds(userIds).stream()
                .collect(Collectors.toMap(SysUser::getUserId, Function.identity(), (k1, k2) -> k2));
        Map<Long, IpRange> rangeMap = rangeListToMap(rangeService.findByIds(rangeIds));

        return records.stream().map(item -> {
            IpAddressResponseVO bean = BeanUtil.toBean(item, IpAddressResponseVO.class);
            bean.setIpFormatValue(NetUtil.longToIpv4(item.getIpValue()));

            Optional.ofNullable(userMap.get(item.getUsageUserId()))
                    .ifPresent(user -> bean.setUsageUserName(user.getUserName()));
            Optional.ofNullable(rangeMap.get(item.getRangeId()))
                    .ifPresent(range -> bean.setRangeName(range.getRangeName()));

            return bean;
        }).collect(Collectors.toList());
    }

    /**
     * 新增IP地址维护结构
     *
     * @param vo 参数接收
     * @return 结果
     */
    @Override
    public int insertIpAddress(IpAddressRequestVO vo) {
        if (IpRangeUtil.isValidIpv4(vo.getIpValue())) {
            throw new ServiceException("IP地址格式错误!");
        }
        long ipv4ToLong = NetUtil.ipv4ToLong(vo.getIpValue());

        IpRange ipRange = rangeService.findById(vo.getRangeId());
        if (ipRange == null) {
            throw new ServiceException("网段不存在!");
        }

        if (ipRange.getStartIp() > ipv4ToLong || ipRange.getEndIp() < ipv4ToLong) {
            throw new ServiceException("IP地址不在网段内!");
        }

        IpAddress ipAddress = findByIpLong(ipv4ToLong);
        if (ipAddress != null) {
            throw new ServiceException("IP地址已存在,请勿重复添加!");
        }
        IpAddress address = IpAddressUtil.convertIpAddress(vo);
        return getBaseMapper().insert(address);
    }

    /**
     * 通过IP查询IP信息
     *
     * @param ipv4ToLong ip
     * @return IpAddress ip信息
     */
    private IpAddress findByIpLong(long ipv4ToLong) {
        return getBaseMapper().selectOne(Wrappers.<IpAddress>lambdaQuery()
                .eq(IpAddress::getHostname, ipv4ToLong)
                .last("LIMIT 1")
        );
    }

    /**
     * 通过IP查询IP信息
     *
     * @param ip ip地址
     * @return IpAddress ip信息
     */
    private IpAddress findByIp(String ip) {
        long ipv4ToLong = NetUtil.ipv4ToLong(ip);
        return findByIpLong(ipv4ToLong);
    }

    /**
     * 修改IP地址维护结构
     *
     * @param vo IP地址维护结构
     * @return 结果
     */
    @Override
    public int updateIpAddress(IpAddressRequestVO vo) {
        IpAddress ipAddress = getBaseMapper().selectById(vo.getId());
        if (ipAddress == null) {
            throw new ServiceException("IP地址不存在!");
        }


        if (IpRangeUtil.isValidIpv4(vo.getIpValue())) {
            throw new ServiceException("IP地址格式错误!");
        }

        long ipv4ToLong = NetUtil.ipv4ToLong(vo.getIpValue());

        if (ipv4ToLong != ipAddress.getIpValue()) {
            IpAddress ipAddress1 = findByIpLong(ipv4ToLong);
            if (ipAddress1 != null && !Objects.equals(ipAddress1.getId(), ipAddress.getId())) {
                throw new ServiceException("IP地址已存在,请勿重复添加!");
            }
        }
        if (!Objects.equals(vo.getRangeId(), ipAddress.getRangeId())) {
            IpRange ipRange = rangeService.findById(vo.getRangeId());
            if (ipRange.getStartIp() > ipv4ToLong || ipRange.getEndIp() < ipv4ToLong) {
                throw new ServiceException("IP地址不在网段内!");
            }
        }
        updateTpAddressEntity(ipAddress, vo);
        ipAddress.setIpValue(ipv4ToLong);

        return getBaseMapper().updateById(ipAddress);
    }

    /**
     * 批量删除IP地址维护结构
     *
     * @param ids 需要删除的IP地址维护结构主键
     * @return 结果
     */
    @Override
    public int deleteIpAddressByIds(List<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return 0;
        }
        return getBaseMapper().deleteBatchIds(ids);
    }

    /**
     * 删除IP地址维护结构信息
     *
     * @param id IP地址维护结构主键
     * @return 结果
     */
    @Override
    public int deleteIpAddressById(Long id) {
        return ipAddressMapper.deleteIpAddressById(id);
    }

    /**
     * 数据导处
     *
     * @param response 响应域
     * @param vo       参数接收
     */
    @Override
    public void export(HttpServletResponse response, IpAddressPageVO vo) {
        TableDataInfo dataInfo = selectIpAddressList(vo);
        ExcelUtil<IpAddressExcelVO> excelUtil = new ExcelUtil<>(IpAddressExcelVO.class);
        List<IpAddressExcelVO> collect = dataInfo.getRows().stream()
                .filter(Objects::nonNull)
                .map(ipAddress -> {
                    IpAddressExcelVO bean = BeanUtil.toBean(ipAddress, IpAddressExcelVO.class);
                    // TODO 设置序号
                    bean.setIndex(null);
                    return bean;
                })
                .collect(Collectors.toList());
        excelUtil.easyExcelExport(response, collect, "sheet", "IP地址数据导出", IpAddressExcelVO.class);
    }

    /**
     * Ip地址统计
     *
     * @param vo 统计参数
     * @return Long 统计结果
     */
    @Override
    public long count(IpAddressCountVO vo) {
        return getBaseMapper().selectCount(Wrappers.<IpAddress>lambdaQuery()
                .eq(Objects.nonNull(vo.getUsageStatus()), IpAddress::getUsageStatus, vo.getUsageStatus())
                .eq(Objects.nonNull(vo.getExpiryStatus()), IpAddress::getExpiryStatus, vo.getExpiryStatus())
        );
    }

    /**
     * Ip地址数据导入
     *
     * @param file 待解析数据
     * @return Boolean 导入结果
     */
    @Override
    public Boolean importExcel(MultipartFile file) {
        try {
            EasyExcelFactory.read(file.getInputStream(), IpAddress.class, new IpRangeListener()).sheet().doRead();
        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        }
        return true;
    }

    /**
     * 批量插入
     *
     * @param arrayList 待插入数据集
     * @return Boolean 插入结果
     */
    @Override
    public Boolean batchInsertion(List<IpAddress> arrayList) {
        return saveBatch(arrayList);
    }

    /**
     * 通过ip值查询
     *
     * @param values ip值
     * @return Map<Long, IpAddress> 查询结果
     */
    @Override
    public Map<Long, IpAddress> findByIpValue(Collection<Long> values) {
        if (CollUtil.isEmpty(values)) {
            return Collections.emptyMap();
        }
        return getBaseMapper().selectList(Wrappers.<IpAddress>lambdaQuery()
                .select(IpAddress::getIpValue, IpAddress::getId)
                .in(IpAddress::getIpValue, values)
        ).stream().collect(Collectors.toMap(IpAddress::getIpValue, Function.identity(), (k1, k2) -> k2));
    }

    /**
     * 通过rangeId查询详情
     *
     * @param rangeId 网段ID
     * @return List<IpAddressDetailVO> 查询结果
     */
    @Override
    public List<IpAddressDetailVO> getByRangeIdInfo(Long rangeId) {
        IpRange ipRange = rangeService.selectIpRangeById(rangeId);
        if (ipRange == null) {
            return Collections.emptyList();
        }
        List<IpAddress> list = getBaseMapper().selectList(Wrappers.<IpAddress>lambdaQuery()
                .eq(IpAddress::getRangeId, rangeId)
        );

        List<IpAddressDetailVO> detailVOList = detailDataHandel(ipRange, list);
        return Collections.emptyList();
    }

    /**
     * 详情结果处理
     *
     * @param ipRange 网段信息
     * @param list    ip数据
     * @return List<IpAddressDetailVO> 操作结果
     */
    private List<IpAddressDetailVO> detailDataHandel(IpRange ipRange, List<IpAddress> list) {
        Map<Long, IpAddress> collect = list.stream().collect(Collectors.toMap(IpAddress::getIpValue, Function.identity(), (k1, k2) -> k2));

        List<IpAddressDetailVO> resultList = new ArrayList<>();
        for (long i = ipRange.getStartIp(); i <= ipRange.getEndIp(); i++) {
            String ipv4 = NetUtil.longToIpv4(i);
            int lastDotIndex = ipv4.lastIndexOf(".");
            String suffix = ipv4.substring(lastDotIndex + 1);

            IpAddressDetailVO detailVO = new IpAddressDetailVO();
            detailVO.setIpValue(ipv4);
            detailVO.setSuffix(suffix);
            IpAddress ipAddress = collect.getOrDefault(i, null);
            detailVO.setId(ipAddress != null ? ipAddress.getId() : null);
            detailVO.setUsageStatus(ipAddress != null ? ipAddress.getUsageStatus() : UasgeStatusEnum.UNUSED);
            resultList.add(detailVO);
        }
        return resultList;
    }

    /**
     * 更新IP地址实体
     *
     * @param ipAddress ip实体
     * @param vo        更新参数
     */
    private void updateTpAddressEntity(IpAddress ipAddress, IpAddressRequestVO vo) {
        ipAddress.setHostname(vo.getHostname());
        ipAddress.setMacAddress(vo.getMacAddress());
        ipAddress.setUsageBizId(vo.getUsageBizId());
        ipAddress.setUsageUserId(vo.getUsageUserId());
        ipAddress.setUsageStatus(vo.getUsageStatus());
        ipAddress.setExpiryStatus(vo.getExpiryStatus());
        ipAddress.setRangeId(vo.getRangeId());
    }

    public static void main(String[] args) {
        String str = "192.168.1.1";
        String substring = str.substring(str.lastIndexOf(".") + 1);
        System.out.println("substring = " + substring);
    }
}
